package at.jku.pervasive.filter;

import java.util.Date;
import java.util.LinkedList;

import at.jku.pervasive.Position;

public class GrubbsTest implements Filter
{
	private double GRUBBS_REFERENCE = 1.5;

	public double getGRUBBS_REFERENCE()
	{
		return GRUBBS_REFERENCE;
	}

	public void setGRUBBS_REFERENCE(double gRUBBSREFERENCE)
	{
		GRUBBS_REFERENCE = gRUBBSREFERENCE;
	}

	@Override
	public LinkedList<Position> applyFilter(LinkedList<Position> lastPositions)
	{
		LinkedList<Double> amountList = new LinkedList<Double>();
		double meanAmount = 0.0;
		double amountVariance = 0.0;
		double grubbsFactor = 0.0;

		amountList = calcVectorAmounts(lastPositions);

		// Mittelwert
		for (int i = 0; i < amountList.size(); i++)
			meanAmount += amountList.get(i);
		meanAmount /= (double) amountList.size();

		// Varianz
		for (int i = 0; i < amountList.size(); i++)
			amountVariance += Math.pow(amountList.get(i) - meanAmount, 2);
		amountVariance /= (double) (amountList.size() - 1);

		// Grubbfaktor
		grubbsFactor = (Math.abs(amountList.getFirst() - meanAmount)) / (Math.sqrt(amountVariance));

		if (grubbsFactor >= GRUBBS_REFERENCE)
		{
			// lastPositions.pop();
			lastPositions.set(0, calcAveragePosition(lastPositions));
			// System.out.println("Grubbed: " + lastPositions.get(0).getX()
			// +"|"+ lastPositions.get(0).getY() +"|"+
			// lastPositions.get(0).getZ());
		}

		return lastPositions;
	}

	private LinkedList<Double> calcVectorAmounts(LinkedList<Position> vectorList)
	{
		LinkedList<Double> returnList = new LinkedList<Double>();
		double amount = 0.0;

		for (int i = 0; i < vectorList.size(); i++)
		{
			amount = Math.sqrt(Math.pow(vectorList.get(i).getX(), 2) + Math.pow(vectorList.get(i).getY(), 2)
					+ Math.pow(vectorList.get(i).getZ(), 2));

			returnList.add(amount);
		}

		return returnList;
	}

	private Position calcAveragePosition(LinkedList<Position> vectorList)
	{
		Position first = vectorList.pop();
		String id = first.getId();
		Date date = first.getDate();
		double newX = 0.0;
		double newY = 0.0;
		double newZ = 0.0;

		if (vectorList.size() > 0)
		{
			for (int i = 0; i < vectorList.size(); i++)
			{
				newX += vectorList.get(i).getX();
				newY += vectorList.get(i).getY();
				newZ += vectorList.get(i).getZ();
			}

			double size = vectorList.size();

			newX /= size;
			newY /= size;
			newZ /= size;

			first = new Position(id, newX, newY, newZ, false, date);
		}

		return first;
	}
}
